【线段树 扫描线】洛谷 P1856 [USACO5.5]矩形周长Picture
2021-09-26 11:04:00 # ACM

题链

题目解析

做两次扫描线,一次扫 $x$,一次扫 $y$;

每次扫到一条线,这条线的贡献就是 加入这条线之前覆盖的长度 与 加入这条线之后覆盖的长度 的绝对值;

注意:当两条线的高度相等时,权值为 $1$ 的先处理;

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define ls rt<<1
#define rs rt<<1|1
#define B1 131
#define B2 13331
#define M1 1000000007
#define M2 1000000009
#define eps 1e-8
#define MAXN 9e18
#define MS 5009

// 洛谷 P1856 [USACO5.5]矩形周长Picture

int n,m,k;
struct node{
int x1,y1;
int x2,y2;
}b[MS];
struct line{
int l,r,h,w;
}a[MS<<1];
int tot;
int tmp[MS<<1], num;
struct nod{
int val;
int mark;
}p[MS<<2];

bool cmp(line t1, line t2){
if(t1.h == t2.h) return t1.w > t2.w;
return t1.h < t2.h;
}

void init_x(){
num = tot = 0;
for(int i=1;i<=n;i++){
++num; tmp[num] = b[i].x1;
++num; tmp[num] = b[i].x2;
}
sort(tmp+1,tmp+num+1);
int len = num; num = 1;
for(int i=2;i<=len;i++){
if(tmp[i] != tmp[i-1]) tmp[++num] = tmp[i];
}
for(int i=1;i<=n;i++){
int l = lower_bound(tmp+1,tmp+num+1,b[i].x1) - tmp;
int r = lower_bound(tmp+1,tmp+num+1,b[i].x2) - tmp;
a[++tot] = {l,r,b[i].y1, 1};
a[++tot] = {l,r,b[i].y2,-1};
}
sort(a+1,a+tot+1,cmp);
}

void init_y(){
num = tot = 0;
for(int i=1;i<=n;i++){
++num; tmp[num] = b[i].y1;
++num; tmp[num] = b[i].y2;
}
sort(tmp+1,tmp+num+1);
int len = num; num = 1;
for(int i=2;i<=len;i++){
if(tmp[i] != tmp[i-1]) tmp[++num] = tmp[i];
}
for(int i=1;i<=n;i++){
int l = lower_bound(tmp+1,tmp+num+1,b[i].y1) - tmp;
int r = lower_bound(tmp+1,tmp+num+1,b[i].y2) - tmp;
a[++tot] = {l,r,b[i].x1, 1};
a[++tot] = {l,r,b[i].x2,-1};
}
sort(a+1,a+tot+1,cmp);
}

void build(int l,int r,int rt){
p[rt] = {0,0};
if(l == r) return;
int m = l+r>>1;
build(l,m,ls);
build(m+1,r,rs);
}

void push_up(int rt,int l,int r){
if(p[rt].mark) p[rt].val = tmp[r+1] - tmp[l];
else if(l == r) p[rt].val = 0;
else p[rt].val = p[ls].val + p[rs].val;
}

void modify(int L,int R,int l,int r,int rt,int val){
if(L <= l && r <= R){
p[rt].mark += val;
push_up(rt,l,r);
return;
}
int m = l+r>>1;
if(m >= L) modify(L,R,l,m,ls,val);
if(m < R) modify(L,R,m+1,r,rs,val);
push_up(rt,l,r);
}

int cal(){
int ans = 0;
build(1,num-1,1);
for(int i=1;i<=tot;i++){
int t = p[1].val;
modify(a[i].l,a[i].r-1,1,num-1,1,a[i].w);
ans += (int)abs(p[1].val - t);
}
return ans;
}

void solve(){
//cin >> n;
for(int i=1;i<=n;i++){
int x1,y1,x2,y2; cin >> x1 >> y1 >> x2 >> y2;
b[i] = {x1,y1,x2,y2};
}
int ans = 0;
init_x(); ans += cal();
init_y(); ans += cal();
cout << ans << "\n";
}

int main(){
ios::sync_with_stdio(false);
int ce = 1;
//cin >> ce;
while(cin >> n){
solve();
}
}
Prev
2021-09-26 11:04:00 # ACM
Next